package com.cloud.basic.MutilThread;

import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.Semaphore;

/**
 * @program: basic
 * @description: 信号量的一个小例子
 * 使用信号量可以很方便的实现线程同步功能，以解决类似于 生产者——消费者之类(及PV操作)的典型问题。
 * @author: Cloud
 * @create: 2020/12/1 11:17:42
 */
public class TestSemaphore {

    // 初始化信号量
    private Semaphore semaphore = new Semaphore(0);

    // 初始化一个队列
    private Queue<String> queue = new LinkedList();

    // 生产者线程
    public void provider(){
        for (int i = 0; i < 10; i++) {
            // 生产一个产品加到队列中
            String product  = String.format("product_%d",i);
            queue.offer(product);
            // 释放许可证，将其返回到信号量。
            semaphore.release();
            System.out.println(String.format("Send sig >>>>>>>>>>>>> %s", product));

            try {
                Thread.sleep(300);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }


    // 消费者线程
    public void customer(){
        try {
            // 从此信号量获取许可证，阻止直到可用，或线程为 interrupted。
            semaphore.acquire();
            // 返回此信号量中当前可用的许可数。
            System.out.println("semaphore.availablePermits() = " + semaphore.availablePermits());
            System.out.println("queue = " + queue);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        String s = queue.poll();
        System.out.println(String.format("Get sig : %s", s));
        System.out.println("queue = " + queue);

        try {
            Thread.sleep(300);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public void RunTest(){
        Runnable runnable = () -> {
            provider();
        };

        Runnable runnable1 = () -> {
            customer();
        };

        runnable.run();
        runnable1.run();

        while (true){
            try {
                Thread.sleep(300);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }

    public static void main(String[] args) {
        TestSemaphore test1 = new TestSemaphore();
        test1.RunTest();
    }
}
